package backstage.runtime;

import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.glu.GLU;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DragDetectEvent;
import org.eclipse.swt.events.DragDetectListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.MouseWheelListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.opengl.GLCanvas;
import org.eclipse.swt.opengl.GLData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.IME;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

//import com.jogamp.opengl.swt.GLCanvas;

import backstage.runtime.ctrl.ControllerConfigSet;
import backstage.runtime.ctrl.ControllerDeviceImpl;
import backstage.runtime.ctrl.KeyboardDeviceImpl;
import backstage.runtime.ctrltool.CtrlSettingDialog;

import keel.gfx.PixelFormat;
import keel.resource.Resource;
import keel.runtime.Cursor;
import keel.runtime.DisplayMode;
import keel.runtime.audio.AudioPlayer;
import keel.runtime.ctrl.ControllerDeviceManager;
import keel.runtime.event.ApplicationEvent;
import keel.runtime.event.Event;

public class KeelRuntimeSWTImpl extends KeelRuntimeImpl{

	class CtrlSettingHandler
    implements WindowListener, ActionListener
{

    public void actionPerformed(ActionEvent e)
    {
        if(e.getSource() == ctrlsettingdialog.okbutton)
        {
            writeConfig();
            dispose();
        } else
        if(e.getSource() == ctrlsettingdialog.updatebutton)
            writeConfig();
        else
        if(e.getSource() == ctrlsettingdialog.cancelbutton)
            dispose();
    }

    public void windowOpened(WindowEvent windowevent)
    {
    }

    public void windowClosing(WindowEvent e)
    {
        dispose();
    }

    public void windowClosed(WindowEvent windowevent)
    {
    }

    public void windowIconified(WindowEvent windowevent)
    {
    }

    public void windowDeiconified(WindowEvent windowevent)
    {
    }

    public void windowActivated(WindowEvent windowevent)
    {
    }

    public void windowDeactivated(WindowEvent windowevent)
    {
    }

    void writeConfig()
    {
        ControllerConfigSet ccs = ctrlsettingdialog.getConfigSet();
        if(ccs != null)
        {
            ControllerConfigSet.setConfigSet(ccs.merge(ControllerConfigSet.getConfigSet()));
            rebuildControllers();
        }
        portManager.saveConversions();
    }

    void dispose()
    {
        ctrlsettingdialog.hide();
        ctrlsettingdialog.dispose();
        ctrlsettingdialog = null;
    }

    CtrlSettingHandler()
    {
    }
}
	 class EmptyAudioPlayer implements AudioPlayer
	{
		public void open(InputStream inputstream) throws IOException {
		}

		public void open(Resource resource) throws IOException {
		}

		public void open(File file) throws IOException {
		}

		public void play() {
		}

		public void stop() {
		}

		public void close() {
		}

		public boolean isOpened() {
			return false;
		}

		public boolean isLoop() {
			return false;
		}

		public void setLoop(boolean flag) {
		}

		public float getVolume() {
			return 0;
		}

		public void setVolume(float f) {
		}

		public int getTotalTime() {
			return 0;
		}

		public int getCurrentTime() {
			return 0;
		}

		public void seek(int i) {
		}
		
	}
	public AudioPlayer getMpegAudioPlayer()
    {
        return new EmptyAudioPlayer();
    }
	
	public KeelRuntimeSWTImpl() {
		displaymodelist = _getDisplayModeList();
		
//		PaletteData palette = new PaletteData(new RGB[] { display.getSystemColor(SWT.COLOR_WHITE).getRGB(), display.getSystemColor(SWT.COLOR_BLACK).getRGB() });
//		ImageData sourceData = new ImageData(getSysCursorWidth(), getSysCursorHeight(), 1, palette);
//		sourceData.transparentPixel = 0;
//		transparentMouseCursor = new org.eclipse.swt.graphics.Cursor(display, sourceData, 0, 0);
	}
	
	protected Event _peekEvent() {
		if(shell!=null && !shell.isDisposed())
			display.readAndDispatch();
		
		 return null;
	}
	
	protected void startControllerConfig()
    {
        try
        {
            if(ctrlsettingdialog == null)
            {
                ctrlsettingdialog = new CtrlSettingDialog(usingdescriptors);
                CtrlSettingHandler csh = new CtrlSettingHandler();
                ctrlsettingdialog.updatebutton.addActionListener(csh);
                ctrlsettingdialog.okbutton.addActionListener(csh);
                ctrlsettingdialog.cancelbutton.addActionListener(csh);
                ctrlsettingdialog.addWindowListener(csh);
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
	
	public void rebuildControllers() {
		ControllerDeviceManager cdm = ControllerDeviceManager.getManager();
        java.util.List devs = cdm.getControllerDevices();
        for(int l = 0; l < devs.size(); l++)
        {
            ControllerDeviceImpl cd = (ControllerDeviceImpl)devs.get(l);
            cd.setConfig(ControllerConfigSet.getConfigSet().getConfig(cd));
        }

        ((KeyboardDeviceImpl)getKeyboardDevice()).updateConfig();
	}

	protected  DisplayMode[] _getDisplayModeList()
	{
		GraphicsDevice gs = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
		java.awt.DisplayMode modes[]=gs.getDisplayModes();
		ArrayList modelist=new ArrayList();
		
		for(int i=0;i<modes.length;++i)
			modelist.add(new DisplayMode(modes[i].getWidth(), modes[i].getHeight(), modes[i].getBitDepth(), modes[i].getRefreshRate()));
		
		return (DisplayMode[])modelist.toArray(new DisplayMode[0]);
	}
	
	protected  PixelFormat[] _getPixelFormatList()
	{
//		GLDrawableFactory glf=GLDrawableFactory.getDesktopFactory();
//		AbstractGraphicsDevice device=glf.getDefaultDevice();
//		GLCapabilities caplist[]=(GLCapabilities[])glf.getAvailableCapabilities(device).toArray(new GLCapabilities[0]);
//		ArrayList pflist=new ArrayList();
//		
//		for(int i=0;i<caplist.length;++i)
//			pflist.add(new PixelFormat(i+1, 
//					caplist[i].getRedBits()+caplist[i].getGreenBits()+caplist[i].getBlueBits()+caplist[i].getAlphaBits(),
//					caplist[i].getRedBits(),caplist[i].getGreenBits(),caplist[i].getBlueBits(),caplist[i].getAlphaBits(), caplist[i].getDepthBits(),
//					caplist[i].getAccumRedBits()+caplist[i].getAccumGreenBits()+caplist[i].getAccumBlueBits()+caplist[i].getAccumAlphaBits(), 
//					caplist[i].getAccumRedBits(),caplist[i].getAccumGreenBits(),caplist[i].getAccumBlueBits(),caplist[i].getAccumAlphaBits(), caplist[i].getStencilBits()));
//		
//		return (PixelFormat[])pflist.toArray(new PixelFormat[0]);
				
		GLCapabilities cap=new GLCapabilities(null);
		return new PixelFormat[]{new PixelFormat(1,
				cap.getRedBits()+cap.getGreenBits()+cap.getBlueBits()+cap.getAlphaBits(),
				cap.getRedBits(),cap.getGreenBits(),cap.getBlueBits(),cap.getAlphaBits(), cap.getDepthBits(),
				cap.getAccumRedBits()+cap.getAccumGreenBits()+cap.getAccumBlueBits()+cap.getAccumAlphaBits(), 
				cap.getAccumRedBits(),cap.getAccumGreenBits(),cap.getAccumBlueBits(),cap.getAccumAlphaBits(), cap.getStencilBits())};
	}
	
	protected void updatePixelFormat() {
		 pixelformatlist = _getPixelFormatList();
	}
	public void yield()
    {
        try
        {
            if(foreprocess)
            {
                if(++loopCount == 15)
                {
                    try
                    {
                        Thread.sleep(1L);
                    }
                    catch(InterruptedException interruptedexception) { }
                    loopCount = 0;
                } else
                {
                    Thread.yield();
                }
            } else
            {
                Thread.sleep(10L);
            }
        }
        catch(Exception exception) { }
    }
	private int convmod(int mod,int t)
	{
		int ret=0;
		if((mod & SWT.CTRL)!=0)
			ret|=keel.runtime.event.InputEvent.CTRL_MASK;
		if((mod & SWT.SHIFT)!=0)
			ret|=keel.runtime.event.InputEvent.SHIFT_MASK;
		if((mod & SWT.ALT)!=0)
			ret|=keel.runtime.event.InputEvent.ALT_MASK;
		if((mod & SWT.COMMAND)!=0)
			ret|=keel.runtime.event.InputEvent.META_MASK;
		
		switch(t)
		{
		case 1:
			ret|=keel.runtime.event.InputEvent.BUTTON1_MASK;
			break;
		case 2:
			ret|=keel.runtime.event.InputEvent.BUTTON2_MASK;
			break;
		case 3:
			ret|=keel.runtime.event.InputEvent.BUTTON3_MASK;	
			break;
		}
		
		return ret;
	}
	private int convcode(int code)
	{
		if(code >= 'a' && code <= 'z')
			return code-'a'+'A';
		switch(code)
		{
		case SWT.ALT:
			return keel.runtime.event.KeyEvent.VK_ALT;
		case SWT.SHIFT:
			return keel.runtime.event.KeyEvent.VK_SHIFT;
		case SWT.CONTROL:
			return keel.runtime.event.KeyEvent.VK_CONTROL;
		case SWT.ARROW_UP:
			return keel.runtime.event.KeyEvent.VK_UP;
		case SWT.ARROW_DOWN:
			return keel.runtime.event.KeyEvent.VK_DOWN;
		case SWT.ARROW_LEFT:
			return keel.runtime.event.KeyEvent.VK_LEFT;
		case SWT.ARROW_RIGHT:
			return keel.runtime.event.KeyEvent.VK_RIGHT;
		case SWT.PAGE_UP:
			return keel.runtime.event.KeyEvent.VK_PAGE_UP;
		case SWT.PAGE_DOWN:
			return keel.runtime.event.KeyEvent.VK_PAGE_DOWN;
		case SWT.HOME:
			return keel.runtime.event.KeyEvent.VK_HOME;
		case SWT.END:
			return keel.runtime.event.KeyEvent.VK_END;
		case SWT.INSERT:
			return keel.runtime.event.KeyEvent.VK_INSERT;
		case SWT.KEYPAD_CR:
		case SWT.CR:
			return keel.runtime.event.KeyEvent.VK_ENTER;
		case SWT.F1:
			return keel.runtime.event.KeyEvent.VK_F1;
		case SWT.F2:
			return keel.runtime.event.KeyEvent.VK_F2;
		case SWT.F3:
			return keel.runtime.event.KeyEvent.VK_F3;
		case SWT.F4:
			return keel.runtime.event.KeyEvent.VK_F4;
		case SWT.F5:
			return keel.runtime.event.KeyEvent.VK_F5;
		case SWT.F6:
			return keel.runtime.event.KeyEvent.VK_F6;
		case SWT.F7:
			return keel.runtime.event.KeyEvent.VK_F7;
		case SWT.F8:
			return keel.runtime.event.KeyEvent.VK_F8;
		case SWT.F9:
			return keel.runtime.event.KeyEvent.VK_F9;
		case SWT.F10:
			return keel.runtime.event.KeyEvent.VK_F10;
		case SWT.F11:
			return keel.runtime.event.KeyEvent.VK_F11;
		case SWT.F12:
			return keel.runtime.event.KeyEvent.VK_F12;
		case SWT.F13:
			return keel.runtime.event.KeyEvent.VK_F13;
		case SWT.F14:
			return keel.runtime.event.KeyEvent.VK_F14;
		case SWT.F15:
			return keel.runtime.event.KeyEvent.VK_F15;
		case SWT.F16:
			return keel.runtime.event.KeyEvent.VK_F16;
		case SWT.F17:
			return keel.runtime.event.KeyEvent.VK_F17;
		case SWT.F18:
			return keel.runtime.event.KeyEvent.VK_F18;
		case SWT.F19:
			return keel.runtime.event.KeyEvent.VK_F19;
		case SWT.F20:
			return keel.runtime.event.KeyEvent.VK_F20;
		case SWT.KEYPAD_MULTIPLY:
			return keel.runtime.event.KeyEvent.VK_MULTIPLY;
		case SWT.KEYPAD_ADD:
			return keel.runtime.event.KeyEvent.VK_ADD;
		case SWT.KEYPAD_SUBTRACT:
			return keel.runtime.event.KeyEvent.VK_SUBTRACT;
		case SWT.KEYPAD_DECIMAL:
			return keel.runtime.event.KeyEvent.VK_DECIMAL;
		case SWT.KEYPAD_DIVIDE:
			return keel.runtime.event.KeyEvent.VK_DIVIDE;
		case SWT.KEYPAD_0:
			return keel.runtime.event.KeyEvent.VK_NUMPAD0;
		case SWT.KEYPAD_1:
			return keel.runtime.event.KeyEvent.VK_NUMPAD1;
		case SWT.KEYPAD_2:
			return keel.runtime.event.KeyEvent.VK_NUMPAD2;
		case SWT.KEYPAD_3:
			return keel.runtime.event.KeyEvent.VK_NUMPAD3;
		case SWT.KEYPAD_4:
			return keel.runtime.event.KeyEvent.VK_NUMPAD4;
		case SWT.KEYPAD_5:
			return keel.runtime.event.KeyEvent.VK_NUMPAD5;
		case SWT.KEYPAD_6:
			return keel.runtime.event.KeyEvent.VK_NUMPAD6;
		case SWT.KEYPAD_7:
			return keel.runtime.event.KeyEvent.VK_NUMPAD7;
		case SWT.KEYPAD_8:
			return keel.runtime.event.KeyEvent.VK_NUMPAD8;
		case SWT.KEYPAD_9:
			return keel.runtime.event.KeyEvent.VK_NUMPAD9;
		case SWT.KEYPAD_EQUAL:
			return keel.runtime.event.KeyEvent.VK_EQUALS;
		case SWT.CAPS_LOCK:
			return keel.runtime.event.KeyEvent.VK_CAPS_LOCK;
		case SWT.NUM_LOCK:
			return keel.runtime.event.KeyEvent.VK_NUM_LOCK;
		case SWT.SCROLL_LOCK:
			return keel.runtime.event.KeyEvent.VK_SCROLL_LOCK;
		case SWT.PAUSE:
			return keel.runtime.event.KeyEvent.VK_PAUSE;
		case SWT.BREAK:
			return keel.runtime.event.KeyEvent.VK_CANCEL;
		case SWT.PRINT_SCREEN:
			return keel.runtime.event.KeyEvent.VK_PRINTSCREEN;
		case SWT.HELP:
			return keel.runtime.event.KeyEvent.VK_HELP;
		case SWT.COMMAND:
			return keel.runtime.event.KeyEvent.VK_META;
		case '`':
			return keel.runtime.event.KeyEvent.VK_BACK_QUOTE;	
		case '\'':
			return keel.runtime.event.KeyEvent.VK_QUOTE;
		}
		
		return code;
	}
	
	private void shellinit()
	{
		shell = new Shell(display,SWT.DIALOG_TRIM);
		//shell.setLayout(new FillLayout());
		
		shell.addShellListener(new ShellListener() {
			public void shellIconified(ShellEvent arg0) {
			}
			
			public void shellDeiconified(ShellEvent arg0) {			
			}
			
			public void shellDeactivated(ShellEvent arg0) {
				postEvent(new ApplicationEvent(ApplicationEvent.DEACTIVATED));
			}
			
			public void shellClosed(ShellEvent arg0) {
				postEvent(new ApplicationEvent(ApplicationEvent.QUIT_REQUESTED));
				arg0.doit=false;
			}
			
			public void shellActivated(ShellEvent arg0) {
				postEvent(new ApplicationEvent(ApplicationEvent.ACTIVATED));
			}
		});
		
		shell.addMouseWheelListener(new MouseWheelListener() {	
			public void mouseScrolled(MouseEvent arg0) {
				postEvent(new keel.runtime.event.MouseEvent(keel.runtime.event.MouseEvent.MOUSE_WHEEL_MOVED,convmod(arg0.stateMask,arg0.button),arg0.x,arg0.y,0,false,arg0.count>0?keel.runtime.event.MouseEvent.WHEEL_FORWARD:keel.runtime.event.MouseEvent.WHEEL_BACKWARD));
			}
		});
		
		shell.addKeyListener(new KeyListener() {
			public void keyReleased(KeyEvent arg0) {
				postEvent(new keel.runtime.event.KeyEvent(keel.runtime.event.KeyEvent.KEY_RELEASED,convmod(arg0.stateMask,0),convcode(arg0.keyCode),arg0.character));
			}
			
			public void keyPressed(KeyEvent arg0) {
				if(arg0.character!='\0')
					postEvent(new keel.runtime.event.KeyEvent(keel.runtime.event.KeyEvent.KEY_TYPED,convmod(arg0.stateMask,0),convcode(arg0.keyCode),arg0.character));
					
				postEvent(new keel.runtime.event.KeyEvent(keel.runtime.event.KeyEvent.KEY_PRESSED,convmod(arg0.stateMask,0),convcode(arg0.keyCode),arg0.character));
			}
		});
		
//		if(comp==null || comp.isDisposed())
//		{
		comp = new Composite(shell, SWT.NONE);
		comp.setLayout(new FillLayout());
		//}
		
//		if(ime!=null)
//		{
//			if(!ime.isDisposed())
//				ime.dispose();
//			ime=null;
//		}
		ime = new IME(shell,SWT.NONE);
		ime.addListener(SWT.ImeComposition, new Listener(){

			public void handleEvent(org.eclipse.swt.widgets.Event arg0) {
				switch (arg0.detail) { 
				case SWT.COMPOSITION_SELECTION:
					break;
				case SWT.COMPOSITION_CHANGED: 
					//if(ime.getCommitCount()>0)
					//{
					//	postEvent(new InputMethodEvent(InputMethodEvent.TEXT_CHANGED,new AttributedString(ime.getText()).getIterator(),ime.getCommitCount()));
						//arg0.doit=false;
					//}
					break;
				case SWT.COMPOSITION_OFFSET:
					break; 
				}
			}
		});
	}
	
//	public void setInputMethodPassiveMode(PassiveInputMethodRequests reqs, boolean floating)
//    {
//		int pos[]=reqs.getCompositionLocation();
//		imepos=new Point(pos[0],pos[1]);
//    }
	
	protected void _createWindow(String s, int i, int j) {
		//_disposeDisplay();
		if(shell==null || shell.isDisposed())
			shellinit();		
		
		if (display.getThread() != Thread.currentThread ())
		{
			final int ii=i;final int jj=j;final String ss=s;
			display.asyncExec(
					new Runnable() {
					   public void run(){
						   shell.setText(ss);
							
							comp.setSize(ii, jj);
							shell.pack();
					   }});
			return;
		}
		
		shell.setText(s);
		//shell.setSize(i, j);
		
		comp.setSize(i, j);
		shell.pack();
		
		//if(!isWindowMode())
		//{
			//GraphicsDevice gs = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
			//if(gs.isDisplayChangeSupported())
			//	gs.setDisplayMode(winDisplayMode);
			
			//shell.setFullScreen(false);
		//}
		
		//shell.open();
	}

	protected boolean _isDisplayAvailable(DisplayMode displaymode1) {
		if (displaymodelist==null) return false;
		
		for(int i=0;i<displaymodelist.length;++i)
			if(displaymode1.equals(displaymodelist[i]))
				return true;
		return false;
	}

	protected void _createDisplay(DisplayMode displaymode1) {
		System.out.println("////////////////use Display//////////////////");
		
		//_disposeDisplay();
		if(shell==null || shell.isDisposed())
			shellinit();
		
		if (display.getThread() != Thread.currentThread ())
		{
			final int ii=displaymode1.getWidth();final int jj=displaymode1.getHeight();
			display.asyncExec(
					new Runnable() {
					   public void run(){
						   comp.setSize(ii, jj);
							shell.pack();
					   }});
			return;
		}
		
		comp.setSize(displaymode1.getWidth(), displaymode1.getHeight());
		shell.pack();
		//shell.setLayout(new FillLayout());
		//shell.setSize(displaymode1.getWidth(), displaymode1.getHeight());
		//shell.layout(true);
		
		//GraphicsDevice gs = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
		
		//if(isWindowMode())
		//	winDisplayMode=gs.getDisplayMode();
		//if(gs.isDisplayChangeSupported())
		//	gs.setDisplayMode(new java.awt.DisplayMode(displaymode1.getWidth(),displaymode1.getHeight(),displaymode1.getBitDepth(),displaymode1.getRefreshRate()));
		//if(gs.isFullScreenSupported())
		//	shell.setFullScreen(true);
		
		//shell.open();
	}

	protected void _disposeDisplay() {
		if (display.getThread() != Thread.currentThread ())
		{
			display.asyncExec(
					new Runnable() {
					   public void run(){
						   if(canvas!=null)
							{
								if(!canvas.isDisposed())
									canvas.dispose();
								canvas=null;
							}
							if(comp!=null)
							{
								if(!comp.isDisposed())
									comp.dispose();
								comp=null;
							}
							if(ime!=null)
							{
								if(!ime.isDisposed())
									ime.dispose();
								ime=null;
							}
							if(shell!=null)
							{
								if(!shell.isDisposed())
									shell.dispose();
								shell=null;
							}
					   }});
			return;
		}
		
		if(canvas!=null)
		{
			if(!canvas.isDisposed())
				canvas.dispose();
			canvas=null;
		}
		if(comp!=null)
		{
			if(!comp.isDisposed())
				comp.dispose();
			comp=null;
		}
		if(ime!=null)
		{
			if(!ime.isDisposed())
				ime.dispose();
			ime=null;
		}
		if(shell!=null)
		{
			if(!shell.isDisposed())
				shell.dispose();
			shell=null;
		}
		
		//if(!isWindowMode())
		//{
		//	GraphicsDevice gs = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
		//	if(gs.isDisplayChangeSupported())
		//		gs.setDisplayMode(winDisplayMode);
		//}
	}
	
	protected long _createGraphics(PixelFormat pixelformat) {

		if(canvas!=null && !canvas.isDisposed())
		{
			if (display.getThread() != Thread.currentThread ())
			{
				display.asyncExec(
						new Runnable() {
						   public void run(){
							   comp.layout(true);
						   }});
				return 1;
			}
			comp.layout(true);
			return 1;
			//if(!canvas.isDisposed())
			//	canvas.dispose();
			//canvas=null;
		}
		
//		GLCapabilities cap=new GLCapabilities(null);
//      cap.setHardwareAccelerated(true);
//      cap.setDoubleBuffered(true);
//      cap.setAccumAlphaBits(pixelformat.getAccumAlphaBits());
//      cap.setAccumBlueBits(pixelformat.getAccumBlueBits());
//		cap.setAccumGreenBits(pixelformat.getAccumGreenBits());
//		cap.setAccumRedBits(pixelformat.getAccumRedBits());
//		cap.setAlphaBits(pixelformat.getAlphaBits());
//		cap.setBlueBits(pixelformat.getBlueBits());
//		cap.setGreenBits(pixelformat.getGreenBits());
//		cap.setRedBits(pixelformat.getRedBits());
//		cap.setDepthBits(pixelformat.getDepthBits());
//		cap.setStencilBits(pixelformat.getStencilBits());
//		canvas = new GLCanvas(comp, SWT.NO_BACKGROUND, null, null, null);
        
		GLData data = new GLData ();
		data.doubleBuffer = true;
		data.accumAlphaSize=pixelformat.getAccumAlphaBits();
		data.accumBlueSize=pixelformat.getAccumBlueBits();
		data.accumGreenSize=pixelformat.getAccumGreenBits();
		data.accumRedSize=pixelformat.getAccumRedBits();
		data.alphaSize=pixelformat.getAlphaBits();
		data.blueSize=pixelformat.getBlueBits();
		data.greenSize=pixelformat.getGreenBits();
		data.redSize=pixelformat.getRedBits();
		data.depthSize=pixelformat.getDepthBits();
		data.stencilSize=pixelformat.getStencilBits();
		canvas = new GLCanvas(comp, SWT.NO_BACKGROUND, data);
		
		canvas.setCurrent();
		context = GLDrawableFactory.getDesktopFactory().createExternalGLContext();
		glu = GLU.createGLU(context.getGL());
		//context = canvas.getContext();

//		canvas.addGLEventListener(new GLEventListener() {
//			
//			public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3,
//					int arg4) {
//			}
//			
//			public void init(GLAutoDrawable arg0) {
//				//postEvent(new ApplicationEvent(ApplicationEvent.UPDATE));
//			}
//			
//			public void dispose(GLAutoDrawable arg0) {
//			}
//			
//			public void display(GLAutoDrawable arg0) {
//				//postEvent(new ApplicationEvent(ApplicationEvent.UPDATE));
//			}
//		});
		
		canvas.addPaintListener(new PaintListener() {
			public void paintControl(PaintEvent arg0) {
				postEvent(new ApplicationEvent(ApplicationEvent.UPDATE));
			}
		});
		
		canvas.addMouseTrackListener(new MouseTrackListener() {
			public void mouseHover(MouseEvent arg0) {
			}
			
			public void mouseExit(MouseEvent arg0) {
				postEvent(new keel.runtime.event.MouseEvent(keel.runtime.event.MouseEvent.MOUSE_EXITED,0,0,0,0,false,0));
			}
			
			public void mouseEnter(MouseEvent arg0) {
				postEvent(new keel.runtime.event.MouseEvent(keel.runtime.event.MouseEvent.MOUSE_ENTERED,0,0,0,0,false,0));
			}
		});
		
		canvas.addMouseMoveListener(new MouseMoveListener() {
			public void mouseMove(MouseEvent arg0) {
				//System.out.println("!!!!!!!!!!!move!!!!!!!!!!"+arg0.x+","+arg0.y);
				if(isdrag)
					postEvent(new keel.runtime.event.MouseEvent(keel.runtime.event.MouseEvent.MOUSE_DRAGGED,convmod(arg0.stateMask,arg0.button),arg0.x,arg0.y,0,false,0));	
				else
					postEvent(new keel.runtime.event.MouseEvent(keel.runtime.event.MouseEvent.MOUSE_MOVED,convmod(arg0.stateMask,arg0.button),arg0.x,arg0.y,0,false,0));
			}
		});
		
		canvas.addDragDetectListener(new DragDetectListener() {
			public void dragDetected(DragDetectEvent arg0) {
				//System.out.println("+++++++++drag++++++++++"+arg0.x+","+arg0.y);
				isdrag=true;
				postEvent(new keel.runtime.event.MouseEvent(keel.runtime.event.MouseEvent.MOUSE_DRAGGED,convmod(arg0.stateMask,arg0.button),arg0.x,arg0.y,0,false,0));	
			}
		});
		
		canvas.addMouseListener(new MouseListener() {	
			public void mouseUp(MouseEvent arg0) {
				//System.out.println("//////////up post//////////"+arg0.x+","+arg0.y+","+arg0.count);
				postEvent(new keel.runtime.event.MouseEvent(keel.runtime.event.MouseEvent.MOUSE_RELEASED,convmod(arg0.stateMask,arg0.button),arg0.x,arg0.y,arg0.count,arg0.button==3,0));
				if(!isdrag)
				{
					//System.out.println("---------click post---------"+arg0.x+","+arg0.y+","+arg0.count);
					postEvent(new keel.runtime.event.MouseEvent(keel.runtime.event.MouseEvent.MOUSE_CLICKED,convmod(arg0.stateMask,arg0.button),arg0.x,arg0.y,arg0.count,false,0));
				}
				isdrag=false;
			}
			
			public void mouseDown(MouseEvent arg0) {
				//System.out.println("\\\\\\\\\\down post\\\\\\\\\\"+arg0.x+","+arg0.y+","+arg0.count);
				postEvent(new keel.runtime.event.MouseEvent(keel.runtime.event.MouseEvent.MOUSE_PRESSED,convmod(arg0.stateMask,arg0.button),arg0.x,arg0.y,arg0.count,false,0));
			}
			
			public void mouseDoubleClick(MouseEvent arg0) {
			}
		});

		shell.open();
		comp.layout(true);
		
		return 1;
	}

	public void _enableInputMethods(boolean b)
    {
		if(shell!=null && !shell.isDisposed() && ime!=null && !ime.isDisposed())
		{
			final boolean bb=b;
			if (display.getThread() != Thread.currentThread ())
			{
				display.asyncExec(
						new Runnable() {
						   public void run(){
							   if(bb)
								   shell.setIME(ime);
								else
									shell.setIME(null);
						   }});
				return;
			}
			if(b)
				shell.setIME(ime);
			else
				shell.setIME(null);
		}
    }
	
	protected boolean _makeCurrent() {
			if(canvas==null || canvas.isDisposed())
				return false;
		if (display.getThread() != Thread.currentThread ())
			return false;
//			display.syncExec(
//					new Runnable() {
//					   public void run(){
//						   canvas.setCurrent();
//					   }});
//		else
			canvas.setCurrent();
//		 while (context.makeCurrent() == GLContext.CONTEXT_NOT_CURRENT) {
//             try {
//				Thread.sleep(100);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//		}
//     }
		
		return context.makeCurrent() != GLContext.CONTEXT_NOT_CURRENT;
	}

	protected void _swapBuffers() {
			if(canvas==null || canvas.isDisposed())
				return;
			if (display.getThread() != Thread.currentThread ())
				return;
//				display.syncExec(
//						new Runnable() {
//						   public void run(){
//							   canvas.swapBuffers();
//						   }});
//			else
			canvas.swapBuffers();
	}

	protected void _free() {
		context.release();
	}

	protected int getScreenPtr() {
		return 0;
	}

	public boolean isGraphicsActive() {		
		return context.isCurrent();
	}
	
//	public static ImageData convertAWTImageToSWT(Image image) {
//        if (image == null) {
//            throw new IllegalArgumentException("Null 'image' argument.");
//        }
//        int w = image.getWidth(null);
//        int h = image.getHeight(null);
//        if (w == -1 || h == -1) {
//            return null;
//        }
//        BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
//        Graphics g = bi.getGraphics();
//        g.drawImage(image, 0, 0, null);
//        g.dispose();
//        return convertToSWT(bi);
//    }
//	
//	public static ImageData convertToSWT(BufferedImage bufferedImage) {
//		if (bufferedImage.getColorModel() instanceof DirectColorModel) {
//			DirectColorModel colorModel = (DirectColorModel)bufferedImage.getColorModel();
//			PaletteData palette = new PaletteData(colorModel.getRedMask(), colorModel.getGreenMask(), colorModel.getBlueMask());
//			ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette);
//			for (int y = 0; y < data.height; y++) {
//				for (int x = 0; x < data.width; x++) {
//					int rgb = bufferedImage.getRGB(x, y);
//					int pixel = palette.getPixel(new RGB((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF)); 
//					data.setPixel(x, y, pixel);
//					if (colorModel.hasAlpha()) {
//						data.setAlpha(x, y, (rgb >> 24) & 0xFF);
//					}
//				}
//			}
//			return data;		
//		} else if (bufferedImage.getColorModel() instanceof IndexColorModel) {
//			IndexColorModel colorModel = (IndexColorModel)bufferedImage.getColorModel();
//			int size = colorModel.getMapSize();
//			byte[] reds = new byte[size];
//			byte[] greens = new byte[size];
//			byte[] blues = new byte[size];
//			colorModel.getReds(reds);
//			colorModel.getGreens(greens);
//			colorModel.getBlues(blues);
//			RGB[] rgbs = new RGB[size];
//			for (int i = 0; i < rgbs.length; i++) {
//				rgbs[i] = new RGB(reds[i] & 0xFF, greens[i] & 0xFF, blues[i] & 0xFF);
//			}
//			PaletteData palette = new PaletteData(rgbs);
//			ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette);
//			data.transparentPixel = colorModel.getTransparentPixel();
//			WritableRaster raster = bufferedImage.getRaster();
//			int[] pixelArray = new int[1];
//			for (int y = 0; y < data.height; y++) {
//				for (int x = 0; x < data.width; x++) {
//					raster.getPixel(x, y, pixelArray);
//					data.setPixel(x, y, pixelArray[0]);
//				}
//			}
//			return data;
//		}
//		return null;
//	}
	
	public void setIconImage(Image image) {
//		if(shell==null || shell.isDisposed())
//			return;
//		
//		org.eclipse.swt.graphics.Image im=new org.eclipse.swt.graphics.Image(display,convertAWTImageToSWT(image));
//		shell.setImages(new org.eclipse.swt.graphics.Image[]{im,im});
	}
	
	public void setCursor(Cursor cursor)
    {
		if(shell==null || shell.isDisposed())
			return;
		
		int t=SWT.CURSOR_ARROW;
		switch(cursor.getType())
		{
		case Cursor.CROSSHAIR_CURSOR:
			t=SWT.CURSOR_CROSS;
			break;
		case Cursor.TEXT_CURSOR:
			t=SWT.CURSOR_IBEAM;
			break;
		case Cursor.WAIT_CURSOR:
			t=SWT.CURSOR_WAIT;
			break;
		case Cursor.SW_RESIZE_CURSOR:
			t=SWT.CURSOR_SIZESW;
			break;
		case Cursor.SE_RESIZE_CURSOR:
			t=SWT.CURSOR_SIZESE;
			break;
		case Cursor.NW_RESIZE_CURSOR:
			t=SWT.CURSOR_SIZENW;
			break;
		case Cursor.NE_RESIZE_CURSOR:
			t=SWT.CURSOR_SIZENE;
			break;
		case Cursor.N_RESIZE_CURSOR:
			t=SWT.CURSOR_SIZEN;
			break;
		case Cursor.S_RESIZE_CURSOR:
			t=SWT.CURSOR_SIZES;
			break;
		case Cursor.W_RESIZE_CURSOR:
			t=SWT.CURSOR_SIZEW;
			break;
		case Cursor.E_RESIZE_CURSOR:
			t=SWT.CURSOR_SIZEE;
			break;
		case Cursor.HAND_CURSOR:
			t=SWT.CURSOR_HAND;
			break;
		case Cursor.MOVE_CURSOR:
			t=SWT.CURSOR_SIZEALL;
			break;
		}
		
		shell.setCursor(display.getSystemCursor(t));
    }
	protected boolean initRuntime(String dist, String dev)
	{
		return true;
	}
	
	protected int getSysCursorWidth()
	{
		return display.getCursorSizes()[0].x;
	}

	protected int getSysCursorHeight()
	{
		return display.getCursorSizes()[0].y;
	}
	
	CtrlSettingDialog ctrlsettingdialog;
	static Display display=new Display();
	
	static
	{
		display.addListener(SWT.Close, new Listener() {
				public void handleEvent(org.eclipse.swt.widgets.Event arg0) {
					// TODO Auto-generated method stub
					System.exit(0);
				}
		});
	}
	
	GLCanvas canvas;
	Shell shell;
	Composite comp;
	IME ime;
	
	//java.awt.DisplayMode winDisplayMode;
	//Point imepos;
	boolean isdrag=false;
	 int loopCount = 0;
	public static GLContext context;
	public static GLU glu;

	//org.eclipse.swt.graphics.Cursor transparentMouseCursor;
}
